#ifndef __H_GAME_H__
#define __H_GAME_H__

#include <deque>
#include <vector>
#include <map>
#include <chrono>
#include "ICC_Timer_Handler.h"
#include "RedisClient.h"
#include "GameBase.h"
#include "DbPart.h"
#include "CClient.h"
#include "def.h"
#include "HostBase.h"
#include "json.h"
#include "5000_record_backend.pb.h"
#include "CRocksdb.h"

using namespace std;

// http server
#include "handler.h"
#include "http.h"
#include "buffer.h"
#include "listener.h"
#include "mainworker.h"
#include "activeevent.h"

#include "CRocksdb.h"

typedef struct HttpData{
    uint32 request_id;
    std::string method;
    std::string target;
    std::string body;
}HttpData;
typedef struct CurlData{
    uint32 callback_id;
    std::string body;
    bool isOK;
}CurlData;
class MainHandler : public HiveNS::Handler
{
public:
    MainHandler();
    virtual ~MainHandler();

    // from Handler
	virtual void onReceiveHttp(HiveNS::Http* pHttp);
	virtual void onCurlResponse(HiveNS::Buffer* pBuffer, uint32 nodeID, uint32 callbackID, bool isRequestOK);
	virtual void onCloseHttp(HiveNS::Http* pHttp);
	virtual void onCloseListener(HiveNS::Listener* pListener);
};
//curl http://127.0.0.1:18401/data -d '{"ccgame_id":103,"data_array":"[]","date":"20240910","number":1200,"result":1,"start_id":-1,"table_name":"game_event"}'
/*
PHP的通信body格式
1 获取记录数据 请求：JSON    http://127.0.0.1:18401/data
{
    "start_id": 1,              // 上一个开始的ID，start_id=-1时，获取最新的number条数据
    "number": 100,              // 数量
    "ccgame_id": 101,           // 子游戏ID
    "table_name": "xxx",        // 表名
    "date": "20240725"          // 日期字符串
}
返回数据：JSON
{
    "result": 0,                // 0为成功 >0 为错误码
    "start_id": 1,              // 上一个开始的ID
    "number": 100,              // 数量
    "ccgame_id": 101,           // 子游戏ID
    "table_name": "xxx",        // 表名
    "date": "20240725",         // 日期字符串
    "data_array": [
        "{}",
        "{}"
    ]                           // JSON字符串数组
}
2 表名
（1）game_event                   事件表
（2）game_round_settle            开奖表
（3）game_round_detail            开奖明细表
（4）game_round_replay            牌局回放表


3. 获取cycle对应数据 请求：JSON  http://127.0.0.1:18401/cycle
{
    "cycle": "xxxxx",           // 玩家下注、结算对应的cycle id
    "ccgame_id": 101,           // 子游戏ID
    "date": "20240725"          // 日期字符串
}
返回数据：JSON
{
    "result": 0,                // 0为成功 >0 为错误码
    "cycle": "xxxxx",           // 玩家下注、结算对应的cycle id
    "ccgame_id": 101,           // 子游戏ID
    "date": "20240725",         // 日期字符串
    "bet": "",                  // 下注信息JSON
    "detail": "",               // 开奖明细JSON
    "settle": ""                // 开奖表数据JSON
}
4. 获取settle数据 请求：JSON http://127.0.0.1:18401/settle
{
    "round_no": "12345",         // 当前局round_no
    "ccgame_id": 101,           // 子游戏ID
    "date": "20240725"          // 日期字符串
}
返回数据：JSON
{
    "round_no": "12345",         // 当前局round_no
    "ccgame_id": 101,            // 子游戏ID
    "date": "20240725",         // 日期字符串
    "settle": ""                // 开奖表数据JSON
}

全局表名：game_event_global
对玩家记录：game_event_101_1_(uid)   game_event_拼接上 ccgame_id + event + uid，记录单个玩家的状态，放在全局表里面
对应的自增IDkey: game_event_101_20240730_id 放在全局表里面
对应的自增IDkey: game_round_settle_101_20240730_id 放在全局表里面
对应的自增IDkey: game_round_detail_101_20240730_id 放在全局表里面

拼出表名： game_event_101_20240730 存储单张表
拼出表名： game_round_settle_101_20240730 存储单张表
拼出表名： game_round_detail_101_20240730 存储单张表


事件表
厂商(app_comp_id)，客户端类型(app_type)，app名称(app_id),  ccgame_id（游戏名称）,  uid，level_id(场次id), room_no(房间号),  round_no(对局号),  event，is_first(是否首次) ,  opreate_time,  amount(押注金额、结算金额),  multi(结算倍数)，ext_json
event： 1-进入房间、2-押注，3-结算, 4-爆炸事件
索引： opreate_time;  level_id(场次id)；round_no(对局号);
bet_(cycleid) -> id game_event 表 ID

开奖表
对局时间(bet_time), 开奖时间(settle_time), 局长秒数(round_sec)，level_id(场次id)， room_no(房间号), 玩家人数(user_num), 对局号( round_no), ai人数(ai_num),
bet_times_user(玩家总下注次数),  玩家总投入(bet_amount_user) , 玩家总产出(settle_amount_user),
bet_times_ai(ai总下注次数),  ai总投入(bet_amount_ai) , ai总产出(settle_amount_ai),
 玩家最大结算金额(settle_amount_max),  玩家最大结算倍数(settle_multi_max),
 爆炸倍数(bomp_multi),
开奖结果(result_string),
ext_json
索引： 对局时间(bet_time)；level_id(场次id)；对局号( round_no)
settle_(round_no) -> id (game_round_settle)


开奖明细表
对局时间(bet_time), 开奖时间(settle_time), 厂商(app_comp_id),游戏类型(app_type),游戏名称(app_id)，level_id(场次id)， room_no(房间号) ,
对局号( round_no), 玩家类型(is_ai), 玩家uid, 玩家下注(bet_amount), 玩家产出(settle_amount), 结算倍数(settle_multi)

排名(round_rank),  投注内容(bet_string),   开奖结果(result_string)
ext_json
索引： 对局时间(bet_time)； 对局号( round_no); 玩家uid; 厂商(app_comp_id); 游戏名称(app_id);
detail_(cycleid) -> id game_round_detail 表 ID
*/

class CHost;
class CGameServer :public BYTimerOject
{
public:
	CGameServer();
	virtual ~CGameServer();
public:
	virtual bool InitGame();
	virtual int OnBYTimeOut(int Timerid);
	int ProcessPacket(SocketHandler* pHandler, NETInputPacket* inputPkg);

	int ProcGameInit(int ev_id, SpiderEvent* pEvent);

    void ResponseError(uint32 request_id, int result);

    // http server 返回response给请求方
    void OnGetMessage(uint32 request_id, const std::string& method, const std::string& target, const std::string& body);
    // curl接收到返回结果
    void OnCurlResponse(uint32 callback_id, const std::string& body, bool isOK);

    void ReceiveHttpData(HttpData& data);
    void ReceiveCurlData(CurlData& data);
    void UpdateHttpServer();

    int CreateActiveEvent();
    void OnActiveEvent();
    int SignalActiveEvent();

    void UpdateCheckRemoveTable(void);
    //测试用
    void test();
    //建库
    bool CreateRocksdb();
    //获取当前日期
    std::string GetCurDayDateString();
    //php获得表的一些数据
    int GetPHPTableData(std::string table_name, int start_id, int64 id, int number, std::vector<std::string>& vecValue);
private:
    int HandleGameEvent(SocketHandler* pHandler, NETInputPacket* inputPkg);
    int HandleRoundSettle(SocketHandler* pHandler, NETInputPacket* inputPkg);
    // int HandleRoundDetail(SocketHandler* pHandler, NETInputPacket* inputPkg);
//    int HandleRefreshConfig(SocketHandler* pHandler, NETInputPacket* inputPkg);

    /*游戏事件上报*/
    bool HandleGameBetReprot(SocketHandler* pHandler, NETInputPacket* inputPkg);
    bool HandleGameSettleReprot(SocketHandler* pHandler, NETInputPacket* inputPkg);
    bool HandleGameEndReprot(SocketHandler* pHandler, NETInputPacket* inputPkg);
    bool HandleGameEnterRoomeprot(SocketHandler* pHandler, NETInputPacket* inputPkg);
    bool HandleGameJackpotReport(SocketHandler *pHandler, NETInputPacket *inputPkg);
    bool HandleGameCancelBetReport(SocketHandler *pHandler, NETInputPacket *inputPkg);

    /*拼接表名*/
    bool ConcatTableName(std::string strName, int32_t ccgame_id, std::string& table_name);
    std::string ConcatTableNameByDate(const std::string& strName, int32_t ccgame_id, const std::string& strDate);
    bool ConcatEventFirstKey(std::string strName, int32_t ccgame_id, EVENT_TYPE type, uint32_t uid, std::string& table_name);
    /*事件表Json*/
    void EventJson(Json::Value& root, EVENT_TYPE type, record::GameClassType gct, ::google::protobuf::Message* stReq);
    void CommGameField(Json::Value& field, record::GameClassType gct);
    
	bool ReadCommonConf(const char* strxml);
protected:
    // 合并ext_json数据
    std::string MergeJsonData(Json::Value& SourceJson, const std::string& DestJson);
    Json::Value ParseExtJson(const std::string& ext_json);
//	map<int, int> m_gameToDstIdMap;
public:
    // http server
    HiveNS::Sync* m_pReceiveLock;
    std::vector<HttpData> m_receiveQueue;
    std::vector<CurlData> m_curlQueue;

    CActiveEvent* m_pActiveEvent;

	CHost* m_pHost;

	int m_httpListenPort;

    //db
    CRocksdb m_rocksdb;
    std::string m_strPath;      //库文件路径
    //std::vector<std::string> m_columnFamilies;  //列族
    
    CRocksdb* m_rocksdbHandler;


};

class LoggerRecordJson
{
public:
    LoggerRecordJson() : m_ArrayJson(Json::arrayValue) {}
    ~LoggerRecordJson()
    {
        if (m_ArrayJson.size() > 0)
        {
            log_info("%s:%s", m_ClassName.c_str(), m_ArrayJson.toStyledString().c_str());
            m_ArrayJson.clear();
        }
    }
// protected:
    void Append(const Json::Value& json)
    {
        m_ArrayJson.append(json);
    }
private:
    Json::Value m_ArrayJson;
    std::string m_ClassName;
};

// 日志写入的时间不计入函数的执行耗时
struct Timer : public LoggerRecordJson
{
    std::chrono::time_point<std::chrono::high_resolution_clock> m_start, m_end;
    std::chrono::duration<float> m_duration;
    Timer()
    {
        m_start = std::chrono::high_resolution_clock::now();
    }
    ~Timer()
    {
        m_end = std::chrono::high_resolution_clock::now();
        m_duration = m_end - m_start;
        float ms = m_duration.count() * 1000.0f;
        log_info("1Timer耗时: %.2f ms \n", ms);
        log_info("2Timer耗时: %.6f ms \n", m_duration.count());
    }
};
#endif


